import os, sys
import subprocess

from string import Template

from configuration import default_path, blender_path, b2cs_path

import mimetypes
mimetypes.add_type("application/x-blender", ".blend")
mimetypes.add_type("image/tga", ".tga")
mimetypes.add_type("application/x-crystalspace.library+xml", ".xml")
mimetypes.add_type("image/x-dds", ".dds")

try:
  # Remove .jpe from mimetype extensions, cause it annoys people.
  from mimetypes import _db
  _db.types_map_inv[True].get("image/jpeg", []).remove('.jpe')
  _db.types_map_inv[True].get("audio/ogg", []).remove('.oga')
except (ValueError, ImportError, ):
  pass


class MissingExecutableDependencyException(Exception):
  def __init__(self, msg):
    self.msg = msg
  def __str__(self):
    return repr(self.msg)

def ExecutableDependencies(exes):
  failed_exes = []
  for exe in exes:
    try:
      p = subprocess.Popen([exe, '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
      s, t = p.communicate()
      #print s, t, p.returncode
    except OSError as e:
      failed_exes.append((exe, e))
  if len(failed_exes):
    s = ''
    for f in failed_exes:
      s += exe +': '+str(e)+' \n '
    raise MissingExecutableDependencyException(s)

def BlenderDependency():
  ExecutableDependencies([blender_path()])

def GetScriptPath(f, fnoext=None):
  dirname = os.path.dirname(f)
  if fnoext == None:
    fnoext = os.path.splitext(os.path.basename(f))[0]
  return os.path.join(dirname, 'b-script-'+fnoext+'.py')

def RunBlenderURI(anURI, scriptPath, pipe=subprocess.PIPE, options={}):
  b = blender_path()
  env = dict(os.environ)
  paths = [] #list(sys.path)
  paths.append(b2cs_path())
  env['PYTHON'] = ''
  env['PYTHONPATH'] = os.pathsep.join(paths)
  env.update(options)
  if anURI == '':
    args = [b, "-b", '-P', scriptPath]
  else:
    args = [b, "-b", anURI, '-P', scriptPath]
    
  p = subprocess.Popen(args, stdout=pipe, stderr=pipe, env=env)
  s, t = p.communicate()
  return s, t, p.returncode
        
def ParseOptionsMap(omap, key, kwargs):
  options_map = {}
  try:
    options_map = omap[key]
  except KeyError:
    return
  new = {}
  for option, conv, default in options_map:
    if option in kwargs:
      new[option] = conv(kwargs[option]) if kwargs[option] != 'None' else None
    else:
      new[option] = default
  kwargs.clear()
  kwargs.update(new)
  
def AssetPathTemplate(omap, key):
  try:
    options_map = omap[key]
  except KeyError:
    options_map = {}
  path = ''
  for option, conv, default in options_map:
    path = os.path.join(path, '${'+str(option)+'}')
  return os.path.join('assets', '${uuid}', '${dstFormat}', path, '${uuid}${extension}')

def AssetPathTemplateFormat(omap, key, dstFormat):
  t = Template(AssetPathTemplate(omap, key))
  return t.safe_substitute(dstFormat=str(dstFormat), extension=str(mimetypes.guess_extension(dstFormat)))
  
def AssetPath(omap, key, anAssetReference, dstFormat, kwargs):  
  t = Template(AssetPathTemplateFormat(omap, key, dstFormat))
  kwargs['uuid'] = str(anAssetReference.id)
  return t.substitute(kwargs)

def AssetPathAbsolute(omap, key, anAssetReference, dstFormat, kwargs): 
  path = AssetPath(omap, key, anAssetReference, dstFormat, kwargs)
  return os.path.join(default_path(), path)

